#include "stdafx.h"
#include "Graphic.h"

PGRAPHIC CreateGraphic( int width, int height, int colorDepth, const RGBQUAD* pColorTbl )
{
	int size = sizeof(GRAPHIC);
	int colorUsed = 0;
	if ( colorDepth <= 8 )
	{
		colorUsed = ( 1 << colorDepth );
		size += sizeof(RGBQUAD) * colorUsed;
	}

	PGRAPHIC pGraphic = (PGRAPHIC)new BYTE[size];
	if ( !pGraphic )
		return NULL;

	BITMAPINFOHEADER& bih = pGraphic->bmInfo.bmiHeader;

	bih.biSize			= sizeof(BITMAPINFOHEADER);
	bih.biWidth			= width;
	bih.biHeight		= -height; // top-down bitmap
	bih.biPlanes		= 1;
	bih.biBitCount		= colorDepth;
	bih.biCompression	= BI_RGB;
	bih.biSizeImage		= 0;
	bih.biXPelsPerMeter	= 0;
	bih.biYPelsPerMeter	= 0;
	bih.biClrUsed		= colorUsed;
	bih.biClrImportant	= 0;

	RGBQUAD* colors = pGraphic->bmInfo.bmiColors;

	if ( !pColorTbl )
	{
		for ( int c = 0; c < colorUsed; c++ )
		{
			colors[c].rgbRed		= (BYTE)c;
			colors[c].rgbGreen		= (BYTE)c;
			colors[c].rgbBlue		= (BYTE)c;
			colors[c].rgbReserved	= 0;
		}
	}
	else
	{
		memcpy( colors, pColorTbl, sizeof(RGBQUAD) * colorUsed );
	}

	int nBitsPerLine = width * colorDepth;
	int nBytesPerLine = (nBitsPerLine+7)/8;
	int nPitchPerLine = (nBytesPerLine + 3) & (~3);

	pGraphic->pitch = nPitchPerLine;
	pGraphic->width = width;
	pGraphic->height = height;

	pGraphic->rcBound.left   = 0;
	pGraphic->rcBound.top    = 0;
	pGraphic->rcBound.right  = width;
	pGraphic->rcBound.bottom = height;

	HDC hdc = GetDC(NULL);

	pGraphic->hBitmap = CreateDIBSection(
		hdc,
		&pGraphic->bmInfo,
		DIB_RGB_COLORS,
		&pGraphic->pBits,
		NULL,
		0 );

	ReleaseDC(NULL,hdc);

	if ( !pGraphic->hBitmap )
	{
		DeleteGraphic(pGraphic);
		pGraphic = NULL;
	}
	else
	{
		ClearGraphic(pGraphic);
	}

	return pGraphic;
}

int SetColorTable( PGRAPHIC g, unsigned startIndex, unsigned entries, const RGBQUAD* pColors )
{
	if ( g->bmInfo.bmiHeader.biBitCount > 8 )
		return 0;

	unsigned maxColors = ( 1 << g->bmInfo.bmiHeader.biBitCount );
	if ( startIndex >= maxColors )
		return 0;

	if ( startIndex + entries > maxColors )
		entries = maxColors - startIndex;

	memcpy( &g->bmInfo.bmiColors[startIndex],
		pColors,
		sizeof(RGBQUAD) * entries );

	// creates a memory DC compatible with the application's current screen.
	HDC hMemDC = CreateCompatibleDC(NULL);
	HGDIOBJ hOldBmp = SelectObject( hMemDC, g->hBitmap );
	SetDIBColorTable( hMemDC, 0, maxColors, g->bmInfo.bmiColors );
	SelectObject( hMemDC, hOldBmp );
	DeleteDC(hMemDC);

	return entries;
}
